﻿using System;
using System.Linq;
using System.ServiceModel;
using System.Web;
using MugenInjection.Interface;

namespace MugenInjection.Wcf
{
    public abstract class MugenWcfApplication : HttpApplication
    {
        #region Fields

        private static IInjector _rootInjector;

        #endregion

        #region Method

        /// <summary>
        /// Handles the Start event of the Application.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected void Application_Start(object sender, EventArgs e)
        {
            lock (this)
            {
                _rootInjector = CreateInjector();
                InjectorContainer.Injector = _rootInjector;
                RegisterCustomBehavior();
                OnApplicationStarted();
            }
        }

        #endregion

        #region Virtual or abstract

        /// <summary>
        /// Creates the <see cref="IInjector"/> that will manage your application.
        /// </summary>
        /// <returns>The created <see cref="IInjector"/>.</returns>
        protected abstract IInjector CreateInjector();

        /// <summary>
        /// Handles the Start event of the Session.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void Session_Start(object sender, EventArgs e)
        {
        }

        /// <summary>
        /// Handles the BeginRequest event of the Application.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void Application_BeginRequest(object sender, EventArgs e)
        {
        }

        /// <summary>
        /// Handles the AuthenticateRequest event of the Application.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void Application_AuthenticateRequest(object sender, EventArgs e)
        {
        }

        /// <summary>
        /// Handles the Error event of the Application.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void Application_Error(object sender, EventArgs e)
        {
        }

        /// <summary>
        /// Handles the End event of the Session.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void Session_End(object sender, EventArgs e)
        {
        }

        /// <summary>
        /// Handles the End event of the Application.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void Application_End(object sender, EventArgs e)
        {
            lock (this)
            {
                if (_rootInjector != null)
                {
                    _rootInjector.Dispose();
                    _rootInjector = null;
                }

                OnApplicationStopped();
            }
        }

        /// <summary>
        /// Creates a injector binding for a <see cref="ServiceHost"/>. If you wish to
        /// provide your own <see cref="ServiceHost"/> implementation, override this method
        /// and bind your implementation to the <see cref="ServiceHost"/> class.
        /// </summary>
        protected virtual void RegisterCustomBehavior()
        {
            if (!_rootInjector.GetBindings(typeof (ServiceHost)).Any())
            {
                _rootInjector.Bind<ServiceHost>().To<MugenInjectionServiceHost>();
            }
        }

        /// <summary>
        /// Called when the application is started.
        /// </summary>
        protected virtual void OnApplicationStarted()
        {
        }

        /// <summary>
        /// Called when the application is stopped.
        /// </summary>
        protected virtual void OnApplicationStopped()
        {
        }

        #endregion
    }
}